package com.server;

import java.awt.geom.FlatteningPathIterator;
import java.awt.print.Book;
import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketException;
import java.sql.Date;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Queue;
import java.util.Set;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import org.hamcrest.core.Is;
import org.junit.experimental.theories.Theories;

import com.client.TcpClient;
import com.dao.DepartmentDao;
import com.dao.PersonDao;
import com.dao.impl.DepartmentDaoImpl;
import com.dao.impl.PersonDaoImpl;
import com.gobal.Gobal;
import com.po.Department;
import com.po.Person;
import com.util.Command;

import oracle.sql.INTERVALYM;

public class TcpServer {

	private static ServerSocket server8888 = null;
	private static Socket socket8888 = null;
	private static TcpServer tcpServer;

	public static ServerSocket getInstance() throws IOException {

		server8888 = new ServerSocket(8888);

		socket8888 = server8888.accept();
		System.out.println("new 8888");

		java.util.Date d = new java.util.Date();
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-mm-dd HH:MM:ss");
		String time = sdf.format(d);
		Gobal.userpool.put(socket8888.getInetAddress().toString(), time);
		ExecutorService executorService = Executors.newFixedThreadPool(20);
		executorService.execute(new Connector(socket8888));

		return server8888;
	}

	public boolean getState() {
		return false;

	}

	public void closeServer8888() {
		try {
			socket8888.close();
			server8888.close();
		} catch (SocketException e) {
			System.out.println("Server is Closed");
		} catch (NullPointerException e) {
			System.out.println("Null pointer");
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();

		}

	}
}

class Connector implements Runnable {

	private Socket socket;

	public Connector(Socket socket) {
		super();
		this.socket = socket;

	}

	private void execute() throws SocketException {
		OutputStream out = null;
		String pre = null;
		String suf = null;
		BufferedReader reader = null;
		try {
			out = socket.getOutputStream();
			reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));

		} catch (IOException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		}

		while (true) {

			if (socket.isClosed()) {
				break;
			}

			try {
				out.write("enter:>\n".getBytes());
				String line = reader.readLine();

				// A-D dName:dName,city:city
				if (line.startsWith(Command.AD)) {
					pre = line.substring(0, Command.SUB).trim();
					suf = line.substring(Command.SUB, line.length());
					Department d = dChange(suf, out);
					DepartmentDao dd = new DepartmentDaoImpl();
					int m = dd.addDepartment(d);
					// out.write((d.getdName() + "::" +
					// d.getCity()).getBytes());
				}

				// U-D did:4,dName:namecg,city:citycg
				if (line.startsWith(Command.UD)) {
					pre = line.substring(0, Command.SUB).trim();
					suf = line.substring(Command.SUB, line.length());
					Department d = dChange(suf, out);
					DepartmentDao dd = new DepartmentDaoImpl();
					int m = dd.updateDepartment(d);
					out.write(("m:" + m).getBytes());
				}

				// D-D did:4
				if (line.startsWith(Command.DD)) {
					pre = line.substring(0, Command.SUB).trim();
					suf = line.substring(Command.SUB, line.length());
					DepartmentDao dd = new DepartmentDaoImpl();
					int did = Integer.parseInt(suf.split(":")[1]);
					int m = dd.deleteDepartment(did);
					out.write(("m:" + m).getBytes());
				}

				// L-DA
				if (line.startsWith(Command.LDA)) {
					DepartmentDao dd = new DepartmentDaoImpl();
					List<Department> dList = new ArrayList<Department>();
					dList = dd.showAllDepartment();
					StringBuffer showSb = new StringBuffer();
					for (Department d : dList) {
						showSb.append("did:" + d.getDid() + ",dname:" + d.getdName() + ",city:" + d.getCity());
					}
					out.write((showSb.toString()).getBytes());
				}

				// A-P
				// pname:qqqqq,birthday:1999-09-09,tel:54785868,departmentId:2,salay:99.99
				if (line.startsWith(Command.AP)) {
					pre = line.substring(0, Command.SUB).trim();
					suf = line.substring(Command.SUB, line.length());
					Person p = pChange(suf, out);
					PersonDao pd = new PersonDaoImpl();
					int m = pd.addPerson(p);
					if (m == 0) {
						out.write("not exist departmentId".getBytes());
					}
				}

				// update person set
				// pname='ze',birthday=to_date('10-12-2000',
				// 'dd-mm-yyyy') ,tel=44444454, departmentId=1, salay=444.44
				// where
				// id=1;
				// U-P
				// id:13,pname:test,birthday:1999-09-09,tel:54785868,departmentId:1,salay:0.0
				if (line.startsWith(Command.UP)) {
					pre = line.substring(0, Command.SUB).trim();
					suf = line.substring(Command.SUB, line.length());
					Person p = pChange(suf, out);
					PersonDao pd = new PersonDaoImpl();
					int m = pd.updatePerson(p);
					if (m == 0) {
						out.write("fail".getBytes());
					}
				}

				// D-P id:13
				if (line.startsWith(Command.DP)) {
					pre = line.substring(0, Command.SUB).trim();
					suf = line.substring(Command.SUB, line.length());
					PersonDao pd = new PersonDaoImpl();
					int id = Integer.parseInt(suf.split(":")[1]);
					int m = pd.deletePerson(id);
					out.write(("m:" + m).getBytes());
				}

				// L-PA
				if (line.startsWith(Command.LPA)) {
					PersonDao pd = new PersonDaoImpl();
					List<Person> pList = new ArrayList<Person>();
					pList = pd.showAllPerson();
					StringBuffer showSb = new StringBuffer();
					for (Person p : pList) {
						showSb.append("id:" + p.getId() + ",pName:" + p.getpName() + ",birthday:"
								+ p.getBirthday().getTime() + ",tel:" + p.getTel() + ",departmentId:"
								+ p.getDepartmentId() + ",salay:" + p.getSalay());
					}
					out.write((showSb.toString()).getBytes());
				}

				// L-PD did:1
				if (line.startsWith(Command.LPD)) {
					pre = line.substring(0, Command.SUB).trim();
					suf = line.substring(Command.SUB, line.length());
					PersonDao pd = new PersonDaoImpl();
					List<Person> pList = new ArrayList<Person>();
					int did = Integer.parseInt(suf.split(":")[1]);
					pList = pd.loadPersonByDepartmentId(did);
					StringBuffer showSb = new StringBuffer();
					for (Person p : pList) {
						showSb.append("id:" + p.getId() + ",pName:" + p.getpName() + ",birthday:"
								+ p.getBirthday().getTime() + ",tel:" + p.getTel() + ",departmentId:"
								+ p.getDepartmentId() + ",salay:" + p.getSalay());
					}
					out.write((showSb.toString()).getBytes());
				}

				if (line.equals("bye")) {
					Gobal.userpool.remove(socket.getInetAddress().toString());
					break;
				}
			} catch (IOException e) {

				e.printStackTrace();

			}

		}
		try {
			reader.close();
			out.close();
			socket.close();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		// socket.close();

	}

	public void run() {
		// TODO Auto-generated method stub
		try {
			execute();
		} catch (Exception e) {
			// TODO Auto-generated catch block
		}
	}

	public Department dChange(String inStr, OutputStream out) throws IOException {
		Department d = new Department();
		String[] array = inStr.split(",");
		Map<String, String> tempMap = new HashMap<String, String>();
		for (String arr : array) {
			String[] subArray = arr.split(":");
			switch (subArray[0].toLowerCase().trim()) {
			case "dname":
				d.setdName(subArray[1]);
				break;
			case "city":
				d.setCity(subArray[1]);
				break;
			case "did":
				d.setDid(Integer.parseInt(subArray[1]));
				break;
			default:
				break;
			}
		}
		return d;
	}

	public Person pChange(String inStr, OutputStream out) throws IOException {
		Person p = new Person();
		String[] array = inStr.split(",");
		Map<String, String> tempMap = new HashMap<String, String>();
		for (String arr : array) {
			String[] subArray = arr.split(":");
			switch (subArray[0].toLowerCase().trim()) {
			// String pName, Date birthday, int tel, int departmentId,
			// double
			// salay
			case "pname":
				p.setpName(subArray[1]);
				break;
			case "birthday":
				java.sql.Date birthday = java.sql.Date.valueOf(subArray[1]);
				p.setBirthday(birthday);
				break;
			case "tel":
				p.setTel(Integer.parseInt(subArray[1]));
				break;
			case "departmentid":
				p.setDepartmentId(Integer.parseInt(subArray[1]));
				break;
			case "salay":
				p.setSalay(Double.parseDouble(subArray[1]));
				break;
			case "id":
				p.setId(Integer.parseInt(subArray[1]));
				break;
			default:
				break;
			}
		}
		return p;
	}

}
